No Library Needed for CSS Transitions

Custom Hook

useStyleTransition.tsx

// @ts-nocheck
import { useEffect, useState } from "react"

const STATE = {
  ENTERING: 'ent',
  ENTERED: 'entd',
  EXITING: 'exit',
  EXITED: 'exitd',
}

function useTransitionState(duration = 1000) {

	const inSeconds = duration * 1000

  const [state, setState] = useState<string>('')

  useEffect(() => {
    let timerId: any

    if (state === STATE.ENTERING) {
      timerId = setTimeout(() => setState(STATE.ENTERED), inSeconds)
    } else if (state === STATE.EXITING) {
      timerId = setTimeout(() => setState(STATE.EXITED), inSeconds)
    }

    return () => timerId && clearTimeout(timerId)

  }, [state, setState])


  return [state, setState]
}

export function useStyleTransitionControl(seconds: number) {
  const [state, setState] = useTransitionState(seconds)

  const enter = () => {
    if (state !== STATE.EXITING) {
      setState(STATE.ENTERING)
    }
  }

  const exit = () => {
    if (state !== STATE.ENTERING) {
      setState(STATE.EXITING)
    }
  }

  return [state, enter, exit]
}

Rendered Component

EmojiExample.tsx

// @ts-nocheck
import styled from "styled-components"
import { useStyleTransitionControl } from "../../lib/useStyleTransition"

export function EmojiFade() {

  const [state, enter, exit] = useStyleTransitionControl(1)

  return (
    <StyledEmoji >
      State: {state}

      <div className={`emoji-cont ${state}`}>
        <span role="img" aria-label="fading emoji"> 🐸 </span>
      </div>

      <button onClick={enter}>
        Enter
      </button>

      <button onClick={exit}>
        Exit
      </button>
    </StyledEmoji>
  )
}

const StyledEmoji = styled.div`
  .emoji-cont{

    transition: all .3s ease-in-out;

    &.ent{ 
      opacity: 1;
    }
    &.entd{ 
      opacity: 1;
    }
    &.exit{ 
      opacity: 0;
    }
    &.exitd{ 
      opacity: 0;
    }

  }
`
I'm ignoring all typescript errors at the top of each file. Still trying to figure that out


Credits